package org.xlp.auto.create.util;


import org.xlp.assertion.AssertUtils;
import org.xlp.auto.create.ControllerAutoCreator;
import org.xlp.auto.create.DaoGroupAutoCreator;
import org.xlp.auto.create.EntityAutoCreator;
import org.xlp.auto.create.ServiceGroupAutoCreator;
import org.xlp.auto.create.exception.AutoCreatorDataLoseException;
import org.xlp.utils.XLPStringUtil;

import java.io.IOException;

/**
 * Description: entity, dao, service, controller java文件自动创建工具类
 * <br/>date: 2023/12/4 17:22
 *
 * @version 1.0
 * @author: xlp
 */
public class AutoCreatorContextUtils {
    /**
     * 根据给定的参数，自动创建实体相关的java文件
     * @param rootPath 文件根路径，不需要包含包名，该参数为空或null抛出空指针异常
     * @param basePackageName 实体相关类所在的根包名称 可为空
     * @param entityName 实体名称，该参数为空或null抛出空指针异常
     * @param subPackageName 实体相关类所在的子包名称
     * @param subPkgAddPrefix 标记子包名是否加上entity，dao, service, controller前缀，true：添加，false：不添加
     *                        即子包名变成以下格式：
     *                        <ul>
     *                           <li>entity.subPackageName</li>
     *                           <li>dao.subPackageName</li>
     *                           <li>service.subPackageName</li>
     *                           <li>controller.subPackageName</li>
     *                        </ul>
     * @param subPkgAddEntityNameSuffix  标记子包名是否加上是否拼接上实体名小写部分 true：添加，false：不添加
     *                                  <p>
     *                                   当最后两个参数都为true时，即子包名变成以下格式：
     *                                  <ul>
     *                                      <li>entity.subPackageName.entityName.toLowerCase()</li>
     *                                      <li>dao.subPackageName.entityName.toLowerCase()</li>
     *                                      <li>service.subPackageName.entityName.toLowerCase()</li>
     *                                      <li>controller.subPackageName.entityName.toLowerCase()</li>
     *                                   </ul>
     *                                   </p>
     * @param createEntity 标记是否创建实体对应的java文件，true：创建，false：不创建
     * @throws NullPointerException 假如根路径或实体名称为空或null，则抛出该异常
     * @throws IOException 创建文件失败，抛出该异常
     * @throws AutoCreatorDataLoseException 创建文件时缺少部分必要信息，则抛出该异常
     */
    public static void autoCreate(String rootPath, String basePackageName, String entityName,
                                  String subPackageName, boolean subPkgAddPrefix,
                                  boolean subPkgAddEntityNameSuffix, boolean createEntity)
            throws IOException, AutoCreatorDataLoseException {
        AssertUtils.isNotNull(rootPath, "rootPath parameter must not be null or empty!");
        AssertUtils.isNotNull(entityName, "entityName parameter must not be null or empty!");
        EntityAutoCreator entityAutoCreator = null;

        String subPkg = XLPStringUtil.emptyTrim(subPackageName);
        subPkg = subPkgAddEntityNameSuffix
                ? (XLPStringUtil.isEmpty(subPkg) ? entityName.toLowerCase() : subPkg + "." + entityName.toLowerCase())
                : subPkg;

        if (createEntity) {
            entityAutoCreator = new EntityAutoCreator();
            entityAutoCreator.setRootPath(rootPath);
            entityAutoCreator.setRootPackageName(basePackageName);
            entityAutoCreator.setEntityName(entityName);
            entityAutoCreator.setSubPackageName(join("entity", subPkg, subPkgAddPrefix));
        }

        DaoGroupAutoCreator daoGroupAutoCreator = new DaoGroupAutoCreator();
        ServiceGroupAutoCreator serviceGroupAutoCreator = new ServiceGroupAutoCreator();

        daoGroupAutoCreator.setRootPath(rootPath);
        serviceGroupAutoCreator.setRootPath(rootPath);
        daoGroupAutoCreator.setRootPackageName(basePackageName);
        serviceGroupAutoCreator.setRootPackageName(basePackageName);
        daoGroupAutoCreator.setEntityName(entityName);
        serviceGroupAutoCreator.setEntityName(entityName);
        daoGroupAutoCreator.setSubPackageName(join("dao", subPkg, subPkgAddPrefix));
        serviceGroupAutoCreator.setSubPackageName(join("service", subPkg, subPkgAddPrefix));

        ControllerAutoCreator controllerAutoCreator = new ControllerAutoCreator(
                serviceGroupAutoCreator.getServiceAutoCreator());
        controllerAutoCreator.setSubPackageName(join("controller", subPkg, subPkgAddPrefix));

        if (entityAutoCreator != null){
            entityAutoCreator.write();
        }
        daoGroupAutoCreator.write();
        serviceGroupAutoCreator.write();
        controllerAutoCreator.write();
    }

    /**
     * 给定的的字符串拼接前缀
     * @param prefix
     * @param sourceStr
     * @param addPrefix
     * @return
     */
    private static String join(String prefix, String sourceStr, boolean addPrefix){
        return addPrefix ? (XLPStringUtil.isEmpty(sourceStr) ? prefix : prefix + "." + sourceStr) : sourceStr;
    }

    /**
     * 根据给定的参数，自动创建实体相关的java文件
     * @param rootPath 文件根路径，不需要包含包名，该参数为空或null抛出空指针异常
     * @param basePackageName 实体相关类所在的根包名称 可为空
     * @param entityName 实体名称，该参数为空或null抛出空指针异常
     * @param subPackageName 实体相关类所在的子包名称
     * @param subPkgAddPrefix 标记子包名是否加上entity，dao, service, controller前缀，true：添加，false：不添加
     *                        即子包名变成以下格式：
     *                        <ul>
     *                           <li>entity.subPackageName</li>
     *                           <li>dao.subPackageName</li>
     *                           <li>service.subPackageName</li>
     *                           <li>controller.subPackageName</li>
     *                        </ul>
     * @param subPkgAddEntityNameSuffix  标记子包名是否加上是否拼接上实体名小写部分 true：添加，false：不添加
     *                                  <p>
     *                                   当最后两个参数都为true时，即子包名变成以下格式：
     *                                  <ul>
     *                                      <li>entity.subPackageName.entityName.toLowerCase()</li>
     *                                      <li>dao.subPackageName.entityName.toLowerCase()</li>
     *                                      <li>service.subPackageName.entityName.toLowerCase()</li>
     *                                      <li>controller.subPackageName.entityName.toLowerCase()</li>
     *                                   </ul>
     *                                   </p>
     * @throws NullPointerException 假如根路径或实体名称为空或null，则抛出该异常
     * @throws IOException 创建文件失败，抛出该异常
     * @throws AutoCreatorDataLoseException 创建文件时缺少部分必要信息，则抛出该异常
     */
    public static void autoCreate(String rootPath, String basePackageName, String entityName,
                                  String subPackageName, boolean subPkgAddPrefix,
                                  boolean subPkgAddEntityNameSuffix)
            throws IOException, AutoCreatorDataLoseException {
        autoCreate(rootPath, basePackageName, entityName, subPackageName, subPkgAddPrefix, subPkgAddEntityNameSuffix, true);
    }

    /**
     * 根据给定的参数，自动创建实体相关的java文件
     * @param rootPath 文件根路径，不需要包含包名，该参数为空或null抛出空指针异常
     * @param basePackageName 实体相关类所在的根包名称 可为空
     * @param entityName 实体名称，该参数为空或null抛出空指针异常
     * @param subPackageName 实体相关类所在的子包名称
     * @param createEntity 标记是否创建实体对应的java文件，true：创建，false：不创建
     * @throws NullPointerException 假如根路径或实体名称为空或null，则抛出该异常
     * @throws IOException 创建文件失败，抛出该异常
     * @throws AutoCreatorDataLoseException 创建文件时缺少部分必要信息，则抛出该异常
     */
    public static void autoCreate(String rootPath, String basePackageName, String entityName,
                                  String subPackageName, boolean createEntity)
            throws IOException, AutoCreatorDataLoseException {
        autoCreate(rootPath, basePackageName, entityName, subPackageName, true, true, createEntity);
    }

    /**
     * 根据给定的参数，自动创建实体相关的java文件
     * @param rootPath 文件根路径，不需要包含包名，该参数为空或null抛出空指针异常
     * @param basePackageName 实体相关类所在的根包名称 可为空
     * @param entityName 实体名称，该参数为空或null抛出空指针异常
     * @param subPackageName 实体相关类所在的子包名称
     * @throws NullPointerException 假如根路径或实体名称为空或null，则抛出该异常
     * @throws IOException 创建文件失败，抛出该异常
     * @throws AutoCreatorDataLoseException 创建文件时缺少部分必要信息，则抛出该异常
     */
    public static void autoCreate(String rootPath, String basePackageName, String entityName,
                                  String subPackageName)
            throws IOException, AutoCreatorDataLoseException {
        autoCreate(rootPath, basePackageName, entityName, subPackageName, true);
    }

    /**
     * 根据给定的参数，自动创建实体相关的java文件
     * @param rootPath 文件根路径，不需要包含包名，该参数为空或null抛出空指针异常
     * @param basePackageName 实体相关类所在的根包名称 可为空
     * @param entityName 实体名称，该参数为空或null抛出空指针异常
     * @throws NullPointerException 假如根路径或实体名称为空或null，则抛出该异常
     * @throws IOException 创建文件失败，抛出该异常
     * @throws AutoCreatorDataLoseException 创建文件时缺少部分必要信息，则抛出该异常
     */
    public static void autoCreate(String rootPath, String basePackageName, String entityName)
            throws IOException, AutoCreatorDataLoseException {
        autoCreate(rootPath, basePackageName, entityName, null);
    }
}
